package com.base.springboot.starter.web.controller;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.base.common.model.po.UserInfo;
import com.base.common.model.po.UserInfoPo;
import com.base.springboot.starter.web.util.AesTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

/**
 * 基础控制器 （可获取用户信息）
 *
 * @author admin
 * @date 2020/9/9 下午5:20
 */
@Slf4j
public class BaseController {
    /**
     * C端平台获取用户信息
     *
     * @return C端当前登录用户信息
     */
    public UserInfoPo getCUserInfoPo() {
        HttpServletRequest request = getHttpServletRequest();

        Map<String, Object> userInfoMap = getUserInfoMap(request);
        Object id = userInfoMap.get(Fields.xId);
        if (ObjectUtil.isNull(id)) {
            return null;
        }

        Object phone = userInfoMap.get(Fields.xPhone);
        Object tokenExpireTime = userInfoMap.get(Fields.xTokenExpireTime);

        UserInfoPo UserInfoPo = new UserInfoPo();
        UserInfoPo.setId(this.getId(id));
        UserInfoPo.setPhone(this.toString(phone));
        if (ObjectUtil.isNotNull(tokenExpireTime)) {
            UserInfoPo.setTokenExpireTime(LocalDateTime.ofEpochSecond(Long.parseLong(this.toString(tokenExpireTime)), 0, ZoneOffset.ofHours(8)));
        }
        log.info("C端当前登录用户信息: {}", UserInfoPo.toString());
        return UserInfoPo;
    }

    /**
     * B端平台获取用户信息
     *
     * @return B端当前登录用户信息
     */
    public UserInfo getBAccountInfo() {
        HttpServletRequest request = getHttpServletRequest();

        Map<String, Object> userInfoMap = this.getUserInfoMap(request);

        Object id = userInfoMap.get(Fields.xId);
        if (ObjectUtil.isNull(id)) {
            return null;
        }

        Object loginCode = userInfoMap.get(Fields.xLoginCode);
        Object name = userInfoMap.get(Fields.xName);
        Object bySystem = userInfoMap.get(Fields.xBtSystem);

        UserInfo userInfo = new UserInfo();
        userInfo.setId(this.getId(id));
        userInfo.setLoginCode(this.toString(loginCode));
        userInfo.setName(this.toString(name));
        userInfo.setBtSystem(this.toString(bySystem));

        log.info("B端当前登录用户信息: {}", userInfo.toString());
        return userInfo;
    }

    /**
     * 获取HttpServletRequest
     *
     * @return HttpServletRequest
     */
    private HttpServletRequest getHttpServletRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        return attributes.getRequest();
    }

    /**
     * 取用户ID
     *
     * @param id 用户ID
     * @return 用户ID
     */
    private long getId(Object id) {
        return id != null && NumberUtil.isLong(id.toString()) ? Long.parseLong(id.toString()) : 0L;
    }

    /**
     * 从request 获取用户信息
     *
     * @param request 请求
     * @return 用户信息
     */
    private Map<String, Object> getUserInfoMap(HttpServletRequest request) {
        Map<String, Object> userInfoMap = new HashMap<>(8);

        String userId = request.getHeader(Fields.xId);
        String token = request.getHeader(Fields.xToken);
        String tokenType = request.getHeader(Fields.xTokenType);
        String tokenExpireTime = request.getHeader(Fields.xTokenExpireTime);
        log.info("当前登录用户信息: userId: {}, tokenType: {}, token: {}, ", userId, tokenType, token);

        if (StrUtil.isBlank(userId) && StrUtil.isNotBlank(token)) {
            JSONObject userJsonObject = AesTokenUtil.getUserJsonObject(token);
            log.info("当前登录用户信息: userJsonObject: {}", userJsonObject.toString());

            tokenType = userJsonObject.getStr(Fields.tokenType);
            userInfoMap.put(Fields.xId, userJsonObject.getStr(Fields.id));
            userInfoMap.put(Fields.xTokenExpireTime, userJsonObject.getStr(Fields.tokenExpireTime));

            if (Fields.B_TOKEN.equals(tokenType)) {
                userInfoMap.put(Fields.xBtSystem, userJsonObject.getStr(Fields.btSystem));
                userInfoMap.put(Fields.xLoginCode, userJsonObject.getStr(Fields.loginCode));
                userInfoMap.put(Fields.xName, userJsonObject.getStr(Fields.name));
            } else {
                userInfoMap.put(Fields.xPhone, userJsonObject.getStr(Fields.phone));
            }
        } else {
            userInfoMap.put(Fields.xId, userId);
            userInfoMap.put(Fields.xTokenExpireTime, tokenExpireTime);

            if (Fields.B_TOKEN.equals(tokenType)) {
                userInfoMap.put(Fields.xBtSystem, request.getHeader(Fields.xBtSystem));
                userInfoMap.put(Fields.xLoginCode, request.getHeader(Fields.xLoginCode));
                userInfoMap.put(Fields.xName, request.getHeader(Fields.xName));
            } else {
                userInfoMap.put(Fields.xPhone, request.getHeader(Fields.xPhone));
            }
        }
        return userInfoMap;
    }

    /**
     * Object To String
     *
     * @param value 内容
     * @return 格式化结果
     */
    private String toString(Object value) {
        return value != null ? value.toString() : null;
    }

    public static final class Fields {
        public static final String xToken = "X-Token";

        public static final String xTokenType = "xc-gateway-token-tt";
        public static final String xId = "xc-gateway-token-id";
        public static final String xPhone = "xc-gateway-token-phone";
        public static final String xTokenExpireTime = "xc-gateway-token-tet";
        public static final String xName = "xc-gateway-token-name";
        public static final String xLoginCode = "xc-gateway-token-logincode";
        public static final String xBtSystem = "xc-gateway-token-btsystem";


        public static final String B_TOKEN = "b";
        public static final String C_TOKEN = "c";

        public static final String tokenType = "tt";
        public static final String id = "id";
        public static final String phone = "phone";
        public static final String tokenExpireTime = "tet";

        public static final String name = "name";
        public static final String loginCode = "loginCode";
        public static final String btSystem = "btSystem";

        private Fields() {
        }
    }
}